package com.wjwframework.jfinal.controller;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jfinal.core.Controller;
import com.jfinal.kit.Prop;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.upload.UploadFile;
import com.wjw.utils.DateUtil;
import com.wjw.utils.GUID;
import com.wjwframework.jfinal.config.BaseConfig;
import com.wjwframework.jfinal.vo.PageNavation;

import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.Thumbnails.Builder;

/**
 * @className BaseController
 * @description 控制器基础类
 * @author wjw
 * @cTime 2016年3月19日下午1:54:52
 * @param <T>
 */
public class BaseController<T extends Model> extends Controller {
	
	protected Logger log = LoggerFactory.getLogger(getClass());
	
	protected static Prop baseProp=	BaseConfig.baseProp;
	
	/**
	 * 封装request中所有参数到Map
	 */
	public Map<String, String> getParamMap() {
		Map<String, String> paramMap = new HashMap<String, String>();
		Enumeration<String> paramNames = getParaNames();
		String paramName = "";
		String paramValue = "";
		while (paramNames.hasMoreElements()) {
			paramName = paramNames.nextElement();
			paramValue = getPara(paramName);
			paramMap.put(paramName, paramValue);
		}
		return paramMap;
	}
	
	/**
	 * 获取前端传来的数组对象并响应成Model列表
	 */
	public List<T> getModels(Class<T> modelClass, String modelName) {
		List<String> nos = getModelsNoList(modelName);
		List<T> list = new ArrayList<T>();
		for (String no : nos) {
			T m = getModel(modelClass, modelName + "[" + no + "]");
			if (m != null) {
				list.add(m);
			}
		}
		return list;
	}
	
	/**
	 * 提取model对象数组的下标
	 */
	private List<String> getModelsNoList(String modelName) {
		// 提取标号
		List<String> list = new ArrayList<String>();
		String modelNameAndLeft = modelName + "[";
		Map<String, String[]> parasMap = getRequest().getParameterMap();
		for (Entry<String, String[]> e : parasMap.entrySet()) {
			String paraKey = e.getKey();
			if (paraKey.startsWith(modelNameAndLeft)) {
				String no = paraKey.substring(paraKey.indexOf("[") + 1,
						paraKey.indexOf("]"));
				if (!list.contains(no)) {
					list.add(no);
				}
			}
		}
		return list;
	}
		
	/**
	 * 过滤记录集合中的字段
	 * @param paramMap
	 */
	protected List<Record> fiterColumnsByList(List<Record> list,String... columns) {
		List<Record> result=new ArrayList<Record>();
		for(Record record:list){
			 for(String column:columns){
				 record.remove(column);
	    	}
			result.add(record);
		}
		return result;
	}
	
	/**
	 * 按记录集中指定字段排序
	 * @param paramMap
	 */
	protected List<Record> sortList(List<Record> list,String column) {
		List<Record> result=new ArrayList<Record>();
		int[] firstASCII=new int[list.size()];
    	int[] index=new int[list.size()];
		for(int i=0;i<list.size();i++){
			firstASCII[i]=list.get(i).getStr(column).charAt(0);
			index[i]=i;
		}
		for (int i = 0; i < firstASCII.length - 1; i++) {
			for (int j = 0; j < firstASCII.length - 1 - i; j++) {
				if (firstASCII[j] > firstASCII[j + 1]) {
					int temp = firstASCII[j];
					firstASCII[j] = firstASCII[j + 1];
					firstASCII[j + 1] = temp;

					int item = index[j];
					index[j] = index[j + 1];
					index[j + 1] = item;
				}
			}
		}
		
		for(int i=0;i<list.size();i++){
			Record re=list.get(index[i]);
			result.add(re);
		}
		
		return result;
	}
	
	/**
	 * 获取项目本地地址
	 */
	public String getBasePath(){
		String basePath = getRequest().getServletContext().getRealPath("/");
		return basePath.substring(0, basePath.length()-1);
	}
	
	/**
	 * 获取本地图片目录相对路径
	 */
	public String getImgPath(){
		String date=DateUtil.formatDate(new Date(), "yyyyMM");
		return "/resource/images/"+date+"/";
	}
	
	/**
	 * 获取本地文件目录相对路径
	 */
	public String getFilePath(){
		String date=DateUtil.formatDate(new Date(), "yyyyMM");
		return "/resource/file/"+date+"/";
	}
	
	/**
	 * 是否是有效的图片格式
	 * @param extension
	 * @return
	 */
	public boolean isValidImg(String extension,String contentType){
		boolean flag=false;
		if(StringUtils.isNotBlank(contentType)){
			if(contentType.startsWith("image")){
				String[] imgExtension=new String[]{".jpg",".jpeg",".png",".bpm",".gif"};
				if(StringUtils.isNotBlank(extension)){
					for(String imgExt:imgExtension){
						if(imgExt.equalsIgnoreCase(extension)){
							flag=true;
							break;
						}
					}
				}			
			}
		}
		return flag;
	}
	
	/**
	 * 上传图片
	 * @param uploadFile UploadFile对象
	 * @return 返回:文件相对路径地址
	 * null:request中没有对应name值的文件流
	 * error:上传失败
	 * invalid:不是合格的图片文件
	 */
	public String uploadImg(UploadFile uploadFile) {
		String result = null;
		String imgPath=getImgPath();
		String contentType = uploadFile.getContentType();
		log.info("contentType:" + contentType);
		String saveDirectory = BaseConfig.baseProp.get("resources_path")+imgPath;
		File dir=new File(saveDirectory);
		if(!dir.exists()){//创建目录
			dir.mkdirs();
		}
		File file = uploadFile.getFile();
		String fileName = uploadFile.getFileName();
		String extension = fileName.substring(fileName.lastIndexOf("."));
		if (isValidImg(extension, contentType)) {
			fileName = GUID.create() + extension;
			try {
				Builder<File> builder=Thumbnails.of(file).scale(1f).outputQuality(1.0f);
				builder.outputFormat(extension.substring(1)); 
				builder.toFile(new File(saveDirectory+fileName));
				result = imgPath+fileName;
			} catch (IOException e) {
				e.printStackTrace();
				result = "error";
			}
		} else {
			result = "invalid";
		}
		return result;
	}
	
	/**
	 * 上传图片
	 * @param uploadFile UploadFile对象
	 * @return 返回:文件相对路径地址
	 * null:request中没有对应name值的文件流
	 * error:上传失败
	 * invalid:不是合格的图片文件
	 */
	public String uploadImg(UploadFile uploadFile,Double scale,Float quality) {
		String result = null;
		String imgPath=getImgPath();
		String contentType = uploadFile.getContentType();
		log.info("contentType:" + contentType);
		String saveDirectory = BaseConfig.baseProp.get("resources_path")+imgPath;
		File dir=new File(saveDirectory);
		if(!dir.exists()){//创建目录
			dir.mkdirs();
		}
		File file = uploadFile.getFile();
		String fileName = uploadFile.getFileName();
		//String extension = fileName.substring(fileName.lastIndexOf("."));
		String extension=".jpg";//质量压缩必须为jpg
		if (isValidImg(extension, contentType)) {
			fileName = GUID.create() + extension;
			try {
				Builder<File> builder=Thumbnails.of(file).scale(scale).outputQuality(quality);
				builder.outputFormat(extension.substring(1)); 
				builder.toFile(new File(saveDirectory+fileName));
				result = imgPath+fileName;
			} catch (IOException e) {
				e.printStackTrace();
				result = "error";
			}
		} else {
			result = "invalid";
		}
		return result;
	}
	
	/**
	 * 上传图片
	 * @param imgName 表单中的file值
	 * @return 返回:文件相对路径地址
	 * null:request中没有对应name值的文件流
	 * error:上传失败
	 * invalid:不是合格的图片文件
	 */
	public String uploadImg(String imgName) throws RuntimeException{
		UploadFile uploadFile=getFile(imgName);
		String result=null;
		String imgPath=getImgPath();
		if(uploadFile==null){
			return null;
		}else{
			String contentType=uploadFile.getContentType();
			log.info("contentType:"+contentType);
			String saveDirectory=BaseConfig.baseProp.get("resources_path")+imgPath;
			File dir=new File(saveDirectory);
			if(!dir.exists()){//创建目录
				dir.mkdirs();
			}
			File file=uploadFile.getFile();
			String fileName = uploadFile.getFileName();
			String extension = fileName.substring(fileName.lastIndexOf("."));
			if(isValidImg(extension,contentType)){
				fileName = GUID.create() + extension;
				try {
					FileUtils.copyFile(file,new File(saveDirectory+fileName));
					result=imgPath+fileName;
				} catch (IOException e) {
					e.printStackTrace();
					result="error";
				}
			}else{
				result="invalid";
			}
			FileUtils.deleteQuietly(file);			//删除缓存文件	
		}
		return result;
	}

	/**
	 * @param imgName 图片名
	 * @param scale 比例
	 * @param quality 质量品质
	 * @return
	 */
	public String uploadImg(String imgName,Double scale,Float quality) throws RuntimeException{
		UploadFile uploadFile=getFile(imgName);
		String result=null;
		String imgPath=getImgPath();
		if(uploadFile==null){
			return null;
		}else{
			String contentType=uploadFile.getContentType();
			log.info("contentType:"+contentType);
			String saveDirectory=BaseConfig.baseProp.get("resources_path")+imgPath;
			File dir=new File(saveDirectory);
			if(!dir.exists()){//创建目录
				dir.mkdirs();
			}
			File file=uploadFile.getFile();
			String fileName = uploadFile.getFileName();
			//String extension = fileName.substring(fileName.lastIndexOf("."));
			String extension=".jpg";
			if(isValidImg(extension,contentType)){
				fileName = GUID.create() + extension;
				try {
					Builder<File> builder=Thumbnails.of(file).scale(scale).outputQuality(quality);
					builder.outputFormat(extension.substring(1));
					builder.toFile(new File(saveDirectory+fileName));
					result=imgPath+fileName;
				} catch (IOException e) {
					e.printStackTrace();
					result="error";
				}
			}else{
				result="invalid";
			}
			FileUtils.deleteQuietly(file);//删除缓存文件
		}
		return result;
	}
	
	/**
	 * 上传图片
	 * @param imgName 表单中的file的name值
	 * 压缩至指定图片尺寸（例如：横400高300），不保持图片比例
	 */
	public String uploadImgSetSize(String imgName,int width,int height) throws RuntimeException{
		UploadFile uploadFile=getFile(imgName);
		String result=null;
		String imgPath=getImgPath();
		if(uploadFile==null){
			return null;
		}else{
			String contentType=uploadFile.getContentType();
			log.info("contentType:"+contentType);
			String saveDirectory=BaseConfig.baseProp.get("resources_path")+imgPath;
			File dir=new File(saveDirectory);
			if(!dir.exists()){//创建目录
				dir.mkdirs();
			}
			File file=uploadFile.getFile();
			String fileName = uploadFile.getFileName();
			String extension = fileName.substring(fileName.lastIndexOf("."));
			if(isValidImg(extension,contentType)){
				fileName = GUID.create() + extension;
				try {
					Builder<File> builder=Thumbnails.of(file);
					builder.forceSize(width,height);//设置尺寸宽度与高度
					builder.outputFormat(extension.substring(1)); 
					builder.toFile(new File(saveDirectory+fileName));						
					result=imgPath+fileName;
				} catch (IOException e) {
					e.printStackTrace();
					result="error";
				}
			}else{
				result="invalid";
			}
			FileUtils.deleteQuietly(file);
		}
		return result;
	}
	
	/**
	 * 删除上传的文件
	 * @param imgName
	 * @return
	 */
	public boolean deleteFile(String filePath){
		if(StringUtils.isBlank(filePath)){
			return false;
		}
		File file=new File(BaseConfig.baseProp.get("resources_path")+filePath);
		return FileUtils.deleteQuietly(file);
	}
	
	/**
	 * 删除上传的文件集合
	 * @param filePathList
	 * @return
	 */
	public boolean deleteFileByList(List<String> filePathList){
		boolean flag=true;
		for(String filePath:filePathList){
			if(StringUtils.isBlank(filePath)){
				continue;
			}
			File file=new File(BaseConfig.baseProp.get("resources_path")+filePath);
			flag= FileUtils.deleteQuietly(file);
		}
		return flag;
	}
	
	/**
	 * 判断是否是Multipart请求
	 * @param request
	 * @return
	 */
	public static boolean isMultipartRequest(HttpServletRequest request){
		String contentType=request.getContentType();
		if(contentType.startsWith("multipart/form-data")){
			return true;
		}
		return false;
	}
	
	/**
	 * 递归删除目录或目录下面的文件 (保留系统资源)
	 * @param file
	 */
	public static void delFile(File file){
		if(file.isDirectory()){
			File[] files=file.listFiles();
			for(int i=0;i<files.length;i++){
				delFile(files[i]);
			}
			file.delete();//删除目录
		}else{
			String fileName=file.getName();
			if(!fileName.startsWith("default_")){
				file.delete();//删除文件
			}
		}
	}
	
	/**
	 * 获取初始化后的分页对象
	 */
	public PageNavation getPageNavation(HttpServletRequest request) {
		Map<String, String> paramMap = getParamMap();
		PageNavation page=new PageNavation(paramMap);
		page.setParamMap(paramMap);
		return page;
	}
	
	/**
	 * 过滤记录集合中的行
	 * @param paramMap
	 */
	protected List<Record> fiterRowsByList(List<Record> list,Map<String, Object> params) {
		List<Record> result=new ArrayList<Record>();
		for(Record record:list){
			Iterator<String> kit=params.keySet().iterator();
			while(kit.hasNext()){
				String key=kit.next();
				Object value=params.get(key);
				Object re_value=record.get("state");
				if(!re_value.equals(value)){
					result.add(record);
				}
			}
		}
		return result;
	}
	
	/**
	 * 截取记录集合中的字段
	 * @param paramMap
	 */
	protected List<Record> updColumnsByList(List<Record> list,String... columns) {
		List<Record> result=new ArrayList<Record>();
		for(Record record:list){
			 for(String column:columns){
				 record.set(column, record.getStr(column).length()>10?record.getStr(column).substring(0, 10):record.getStr(column));
	    	}
			result.add(record);
		}
		return result;
	}
	
}
